// +build !windows

package cmd

import (
	"errors"
	"golang.org/x/net/context"
	"os/exec"
	"syscall"
)

type Result struct {
	output string
	err    error
}

// 执行shell命令，可设置执行超时时间
func ExecShell(ctx context.Context, command string) (string, error) {
	cmd := exec.Command("/bin/bash", "-c", command)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: true,
	}
	resultChan := make(chan Result)
	go func() {
		output, err := cmd.CombinedOutput()
		resultChan <- Result{string(output), err}
	}()
	select {
	case <-ctx.Done():
		if cmd.Process.Pid > 0 {
			syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
		}
		return "", errors.New("timeout killed")
	case result := <-resultChan:
		return result.output, result.err
	}
}

func ExecCommand(cmdStr string) (msg string, err error) {
	cmd := exec.Command("bash", "-c", cmdStr)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return msg, fmt.Errorf("failed to execute command: %v, output: %s", err, output)
	}
	return string(output),err
}

func CheckCmd(cmd string) bool {
	_, err := exec.LookPath(cmd)
	if err != nil {
		return false
	}
	return true
}

func ExecSSHCmdByPwd(host, user, password, command string) (string, error) {
	// 创建 SSH 客户端配置
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.Password(password),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 忽略主机密钥验证，这是一个简单的示例，请注意潜在的安全风险
	}

	// 建立 SSH 连接
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", host), config)
	if err != nil {
		return "", fmt.Errorf("failed to dial: %w", err) // 返回错误对象
	}
	defer client.Close()

	// 执行命令
	session, err := client.NewSession()
	if err != nil {
		return "", fmt.Errorf("failed to create session: %w", err) // 返回错误对象
	}
	defer session.Close()

	output, err := session.CombinedOutput(command)
	if err != nil {
		return "", fmt.Errorf("%s: %w", string(output), err) // 返回错误对象和 stderr 输出
	}

	return string(output), nil
}

func ExecSSHCmdByKey(host, user, key, command string) (string, error) {

	// 创建签名器
	signer, err := ssh.ParsePrivateKey([]byte(key))
	if err != nil {
		return "", fmt.Errorf("failed to parse private key: %v", err)
	}

	// 创建 SSH 客户端配置
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 忽略主机密钥验证，这是一个简单的示例，请注意潜在的安全风险
	}

	// 建立 SSH 连接
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:22", host), config)
	if err != nil {
		return "", fmt.Errorf("failed to dial: %v", err)
	}
	defer client.Close()

	// 执行命令
	session, err := client.NewSession()
	if err != nil {
		return "", fmt.Errorf("failed to create session: %v", err)
	}
	defer session.Close()

	output, err := session.CombinedOutput(command)
	if err != nil {
		return "", fmt.Errorf("failed to run command: %v", err)
	}

	return string(output), nil
}